package org.ocean.general.sample.helper;

import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.decorators.SoftCache;
import org.apache.ibatis.cache.impl.PerpetualCache;
import org.apache.ibatis.reflection.MetaObject;
import org.ocean.general.sample.exception.BatisException;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BatisHelper {

    public static final Cache CLASS_CACHE = new SoftCache(new PerpetualCache("MAPPER_CLASS_CACHE"));
    public static Method method;

    static {
        try {
            Class<?> metaClass = Class.forName("org.apache.ibatis.reflection.SystemMetaObject");
            method = metaClass.getDeclaredMethod("forObject", Object.class);
        } catch (Exception e1) {
            try {
                Class<?> metaClass = Class.forName("org.apache.ibatis.reflection.MetaObject");
                method = metaClass.getDeclaredMethod("forObject", Object.class);
            } catch (Exception e2) {
                throw new BatisException(e2.getMessage());
            }
        }

    }

    public static Class<?> getMapperClass(String msId){
        if(msId.indexOf(".")==-1){
            throw new BatisException("当前MappedStatement的id"+msId+"不符合MappedStatement的规则");
        }
        String mapperClass = msId.substring(0,msId.lastIndexOf("."));
        Class<?> mapperClassCache = (Class<?>) CLASS_CACHE.getObject(mapperClass);
        if(null != mapperClassCache){
            return mapperClassCache;
        }
        ClassLoader[] classLoaders = getClassLoaders();
        for (ClassLoader classLoader : classLoaders) {
            if(null != classLoader){
                try {
                    mapperClassCache =Class.forName(mapperClass,true,classLoader);
                    if(null != mapperClassCache){
                        break;
                    }
                } catch (ClassNotFoundException e) {
                    throw new BatisException("无法加载ClassLoader"+mapperClass);
                }
            }
        }
        if(mapperClassCache == null){
            throw new BatisException("无法找到Mapper类"+mapperClass);
        }
        CLASS_CACHE.putObject(mapperClass,mapperClassCache);
        return mapperClassCache;
    }

    public static ClassLoader[] getClassLoaders(){
        return new ClassLoader[]{Thread.currentThread().getContextClassLoader(),BatisHelper.class.getClassLoader()};
    }

    public static String getMethodName(String msId){
        return msId.substring(msId.lastIndexOf(".")+1);
    }

    public static MetaObject forObject(Object object){
        MetaObject metaObject = null;
        try {
             metaObject = (MetaObject) method.invoke(null,object);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return metaObject;
    }


    private static Pattern pattern = Pattern.compile("[A-Z]");
    private static Pattern patternLower = Pattern.compile("_(\\w)");

    public static String getTableName(String name){
        Matcher matcher = pattern.matcher(name);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }


    public static String getTableField(String field){
        Matcher matcher = pattern.matcher(field);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    public static String getGenerationKey(String field){
        String key = getTableField(field);
        return key.substring(1,key.length());
    }

    public static String filedCapital(String field){
        field = field.toLowerCase();
        Matcher matcher = patternLower.matcher(field);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb,  matcher.group(1).toUpperCase());

        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 大写字母转小写并且在之前附加下划线
     * @param name
     * @return
     */
    public static String filedToLowCase(String name){
        char[] bytes = name.toCharArray();
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            if(String.valueOf(bytes[i]).toUpperCase().equals(String.valueOf(bytes[i]))){
                stringBuffer.append("_").append(String.valueOf(bytes[i]).toLowerCase());
            }else {
                stringBuffer.append(bytes[i]);
            }
        }
        return  stringBuffer.toString();
    }

}
